import 'package:dio/dio.dart';
import 'package:logger/logger.dart';

import '../../../data/db/providers/bt_order_provider.dart';
import '../../../data/dio/api/bt_dio_network.dart';
import '../../../data/dio/api/bt_net_data_source.dart';
import '../../../data/models/bt_block.dart';
import '../../../data/models/bt_oss_policy.dart';
import '../../../data/models/bt_update_avatar_result.dart';
import '../../../data/models/bt_user_info.dart';
import '../../../data/stats/bt_log_pages.dart';
import '../../../data/stats/bt_log_pv_manger.dart';
import '../../../data/store/bt_logon_data.dart';
import '../../../data/store/bt_hive_logon_store.dart';
import '../../../part/bt_rc_im_engine.dart';
import '../../../utils/bt_tool_utils.dart';
import '../../utils/bt_constants.dart';
import '../../utils/bt_event_bus.dart';

class BtProfileRepository {
  final logger = Logger();

  final BtNetDataSource network = BtDioNetwork();

  void logout(Function(bool success, String msg) onResult) {
    var map = <String, String>{};

    network.logout(map).then((result) {
      if (result.isSuccess) {
        BtHiveLogonStore().deleteData();
        BtRcImEngine().destroy();
        resetAppConfigVersion();

        BtLogPvManger.stat(page: BtLogPages.logout);
      }
      onResult(result.isSuccess, result.isSuccess ? 'Success' : result.msg);
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void saveUserInfo(String nickname, String birthday, Function(bool success, String msg) onResult) {
    var map = <String, String>{};
    if (nickname.isNotEmpty) {
      map['nickname'] = nickname;
    }
    if (birthday.isNotEmpty) {
      map['birthday'] = birthday;
    }

    network.saveUserInfo(map).then((result) {
      if (result.isSuccess) {
        eventBus.fire(BtEventFn('freshUserInfo'));
      }
      onResult(result.isSuccess, result.isSuccess ? 'Success' : result.msg);
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void deleteAccount(Function(bool success, String msg) onResult) {
    var map = <String, String>{};

    network.deleteAccount(map).then((result) {
      if (result.isSuccess) {
        BtOrderProvider().deleteAll();
        BtHiveLogonStore().deleteData();
        BtRcImEngine().destroy();
        resetAppConfigVersion();

        BtLogPvManger.stat(page: BtLogPages.deleteAccount);
      }
      onResult(result.isSuccess, result.isSuccess ? 'Success' : result.msg);
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void removeBlock(String blockUserId, Function(bool success, String msg) onResult) {
    var map = <String, String>{};
    map['blockUserId'] = blockUserId;

    network.removeBlock(map).then((result) {
      if (result.isSuccess) {
        eventBus.fire(BtEventFn(freshBlockList));
      }
      onResult(result.isSuccess, result.isSuccess ? 'Success' : result.msg);
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void getBlockList(int page, int limit, Function(List<BtBlock>) onResult) {
    var map = <String, dynamic>{};

    network.getBlockList(map).then((blockListResult) {
      if (blockListResult.isSuccess) {
        onResult(blockListResult.data ?? []);
      }
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void freshUserInfo(String userId, String accessToken, Function(BtUserInfo?) onResult) {
    var map = <String, String>{};
    map['userId'] = userId;

    network.getUserInfo(map).then((userInfoResult) {
      if (userInfoResult.isSuccess) {
        BtHiveLogonStore().putData(BtLogonData(
          token: accessToken,
          userId: userInfoResult.data!.userId,
          userType: userInfoResult.data!.userType,
          nickname: userInfoResult.data!.nickname,
          avatarUrl: userInfoResult.data!.avatarUrl,
          avatarThumbUrl: userInfoResult.data!.avatarThumbUrl,
          loginPkgName: userInfoResult.data!.loginPkgName ?? '',
          country: userInfoResult.data!.country ?? '',
          birthday: userInfoResult.data!.birthday,
          availableCoins: userInfoResult.data!.availableCoins ?? 0,
        ));

        onResult(userInfoResult.data);
      }
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void fetchOssPolicy(Function(BtOssPolicy?) onResult) {
    var map = <String, dynamic>{};
    network.getOssPolicy(map).then((result) {
      if (result.isSuccess) {
        onResult(result.data);
      }
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }

  void updateAvatar(String avatarPath,
      Function(bool success, String msg, BtUpdateAvatarResult? updateAvatarResult) onResult) {
    var map = <String, String>{};
    map['avatarPath'] = avatarPath;

    network.updateAvatar(map).then((result) {
      if (result.isSuccess) {
        eventBus.fire(BtEventFn('freshUserInfo'));

        BtLogPvManger.stat(page: BtLogPages.editAvatar);
      }
      onResult(result.isSuccess, result.isSuccess ? 'Success' : result.msg, result.data);
    }).catchError((error) {
      // non-200 error goes here.
      switch (error.runtimeType) {
        case DioException:
          // Here's the sample to get the failed response error code and message
          final res = (error as DioException).response;
          logger.e('Got error : ${res?.statusCode} -> ${res?.statusMessage}');
          break;
        default:
          logger.e('Error occurred: $error');
          break;
      }
    });
  }
}
